package org.lib.mysqlhello.tcache;

import java.time.Duration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Caching配置
 * @author ben
 * @date 2021-08-26 16:16:26 CST
 */
@Configuration
public class AppCacheCofig {

	/**
	 * RedisCacheConfiguration定制
	 * 修改后，实体类不需要 implements Serializable
	 * @author ben
	 * @date 2021-08-26 19:50:38 CST
	 * @return
	 */
	@Bean
	public RedisCacheConfiguration redisCacheConfiguration() {
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		
		// 标记为过时
//		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		// 替代上面的过时方法
		om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, 
				JsonTypeInfo.As.WRAPPER_ARRAY);
		
		jackson2JsonRedisSerializer.setObjectMapper(om);
		
		RedisSerializationContext.SerializationPair<Object> pair = 
				RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);
		
		RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
				.entryTtl(Duration.ofSeconds(300))
				.serializeValuesWith(pair);
		
		return redisCacheConfiguration;
	}
	
	/**
	 * RedisCacheManager定制
	 * 有上面的 RedisCacheConfiguration 定制后，不清楚这个的用途，TODO
	 * @author ben
	 * @date 2021-08-26 20:15:33 CST
	 * @param redisConnectionFactory
	 * @return
	 */
	@Bean
	public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
		// 初始化一个RedisCacheWriter
		RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
		RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, this.redisCacheConfiguration());
		return cacheManager;
	}
	
}
